<script setup >
import { ref, reactive, onMounted } from 'vue'
import * as d3 from 'd3';
import { zoom,zoomIdentity  } from 'd3-zoom';
import axios from "axios";


const d3Ref = ref(null)

onMounted(() => {
  getInitD3()
})

// 定义一个辅助函数，用于生成唯一的ID
const DOM = (function () {
  var count = 0;
  function uid(name) {
    return new Id("O-" + (name == null ? "" : name + "-") + ++count);
  }
  function Id(id) {
    this.id = id;
    this.href = new URL(`#${id}`, location).href;
  }

  Id.prototype.toString = function () {
    return "url(" + this.href + ")";
  };

  // 返回 uid 函数，使其可以被外部访问
  return {
    uid: uid
  };
})();

//初始化d3
const getInitD3 = () => {
  axios.get('http://localhost:2000/echarts.json').then(res => {
    const width = 1442;
    const height = 821;
    let currentTransform = zoomIdentity;
    const color = d3.scaleSequential([8, 0], d3.interpolateMagma);

    const treemap = data => d3.treemap()
        .size([width, height])
        .paddingOuter(1)
        .paddingTop(20)
        .paddingInner(1)
        .round(true)
        .tile(d3.treemapBinary)
        (d3.hierarchy(data)
            .sum(d => d.scale)
            .sort((a, b) => b.scale - a.scale)
        );

    // 使用处理后的数据创建 treemap
    // const root = treemap(processedData);
    const root = treemap(res.data);

    const svg = d3
        .select(d3Ref.value)
        .append("svg:svg")
        .attr("width", width)
        .attr("height", height)
        .attr("viewBox", [0, 0, width, height])
        .attr("style", "max-width: 100%; height: auto; overflow: visible; font: 10px sans-serif;");
    const g = svg.append('g');

    const shadow = DOM.uid("shadow");
    svg.append("filter")
        .attr("id", shadow.id)
        .append("feDropShadow")
        .attr("flood-opacity", 0.5)
        .attr("stdDeviation", 3);

    const node = g.selectAll("g")
        .data(d3.group(root, d => d.height))
        .join("g")
        .attr("filter", shadow)
        .selectAll("g")
        .data(d => d[1])
        .join("g")
        .attr("transform", d => `translate(${d.x0},${d.y0})`);

    const zoomed = (event) => {
      currentTransform = event.transform;
      g.attr('transform', event.transform);
    };

    const zoomBehavior = zoom()
        .scaleExtent([1, 3])
        .on('zoom', zoomed);
    svg.call(zoomBehavior);
    const format = d3.format(",d");
    node.append("title")
        .text(d => `${d.ancestors().reverse().map(d => d.data.name).join("/")}\n${format(d.data.parent)}`);

    node.append("rect")
        .attr("id", d => (d.nodeUid = DOM.uid("node")).id)
        .attr("fill", d => {
          // console.log(d)
          //设置各层级颜色depth
          return color(d.height)
        })
        .attr("width", d => {
          return d.x1 - d.x0
        })
        .attr("height", d => d.y1 - d.y0);

    node.append("clipPath")
        .attr("id", d => (d.clipUid = DOM.uid("clip")).id)
        .append("use")
        .attr("xlink:href", d => {
          return d?.nodeUid.href
        });
    // 文本渲染
    node.append("text")
        .attr("clip-path", d => d.clipUid.id)
        .selectAll("tspan")
        .data(d => {
          //表示只有四级显示
          if (d.depth < 3) {
            return d.data.name.split(/(?=[A-Z][^A-Z])/g)
          }
          return d.data.name.split(/(?=[A-Z][^A-Z])/g).concat(format(d.data.parent))
        })
        .join("tspan")
        .attr("fill-opacity", (d, i, nodes) => {
          return i === nodes.length - 1 ? 0.7 : null
        })
        .style("color", "white")
        .text(d => d);

    node.each(function (d) {
      const nodeWidth = d.x1 - d.x0;
      const nodeHeight = d.y1 - d.y0;
      const textElement = d3.select(this).select("text");

      // 如果节点太小，就隐藏文本
      if (nodeWidth < 20 || nodeHeight < 10) {
        textElement.style("display", "none");
      } else {
        // 调整文本位置和大小
        textElement.selectAll("tspan")
            .attr("x", 3)
            .attr("y", (d, i, nodes) => `${(i === nodes.length - 1 ? 1 : 0.3) + 1.1 + i * 0.9}em`)
            .style("font-size", Math.min(nodeWidth / 10, nodeHeight / 5, 10) + "px");
      }
    });
    node.filter(d => d.children).selectAll("tspan")
        .attr("dx", 3)
        .attr("y", 13);

    node.filter(d => !d.children).selectAll("tspan")
        .attr("x", 3)
        .attr("y", (d, i, nodes) => `${(i == nodes.length - 1) * 0.3 + 1.1 + i * 0.9}em`);
  })

}


</script>
<template>
  <div class="map" ref="d3Ref"></div>
</template>

<style scoped lang="scss"></style>